package proTrack;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import proTrack.model.Account;
import proTrack.model.State;

import com.sun.security.auth.callback.TextCallbackHandler;



public class ProTrack {

	private Operation ops;
	private PrintWriter writer;
	private LoginContext loginContext;


	public ProTrack(final Operation ops, final PrintWriter writer) {
		this.ops = ops;
		this.writer = writer;
	}



	private boolean process(final String c) {
		String comm = c.trim();
		if (comm.toLowerCase().equals("exit")) {
			ops.exit();
			return true;
		} else if (comm.equals("commit")) {
			ops.commit();
			return false;
		} else if (comm.equals("rollback")) {
			ops.rollback();
			return false;
		}
		
		if (!comm.matches("(c|l|s|d)\\s(u|j|s)(\\s+\\S+)*")) {
			writer.write("Improper usage.\n");
			writer.flush();
			return false;
		}
		char command = comm.charAt(0);
		char object = comm.charAt(2);
		String[] params = comm.substring(3).trim().split("\\s+", 2);
		process(command, object, params);

		return false;
	}


	private void process(final char command, final char object, final String[] params) {
		switch (command) {
		case 'c':
			switch (object) {
			case 'u':
				ops.createUser(params[0], params[1]);
				break;
			case 'j':
				// desc., handler, state
				ops.createJob(params[1], params[0], params[2]);
				break;
			case 's':
				ops.createState(params[0]);
				break;

			default:
				break;
			}
			break;
		case 'd':
			switch (object) {
			case 'u':
				ops.deleteUser(params[0]);
				break;
			case 'j':
				ops.deleteJob(params[0]);
				break;
			case 's':
				ops.deleteState(params[0]);
				break;
			default:
				break;
			}
			break;
		case 'l':
			List<? extends Object> list;
			switch (object) {
			case 'u':
				list = ops.getAllAccounts();
				break;
			case 'j':
				list = listJobs(params);
				break;
			case 's':
				list = ops.getAllStates();
				break;	

			default:
				list = new ArrayList<Object>();
				break;
			}
			int i = 0;
			for (Object o : list){
				writer.write(++i + "\t" + o.toString() + "\n");
			}
			writer.flush();
			break;
		case 's':
			switch (object) {
			case 'u':

				break;
			case 'j':
				ops.setJobNextState(params[0], params[1]);
				break;
			case 's':
				ops.setSuccessor(params[0], params[1]);
				break;
			default:
				break;
			}
			break;

		default:
			break;
		}

	}

	private List<? extends Object> listJobs(final String[] params) {
		Class<?> type = Account.class;
		if ("JobsByState".equals(params[0])) {
			type = State.class;
		}
		return ops.getJobs(params[0], params.length > 1 ? params[1] : null, type);
	}



	public static void main(final String[] args) throws Exception {
		EntityManagerFactory f = Persistence.createEntityManagerFactory("persistenceUnitName");
		Operation ops = new Operation(f);
		ProTrack p = new ProTrack(ops, new PrintWriter(System.out));
		Account acc = p.authenticate();
		ops.setAccount(acc);
		 
		 

		 System.out.println("Welcome to ProTrack");
		 
		 boolean exit = false;
		 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		 while(!exit) {
			 System.out.println("Next command:");
			 String command = reader.readLine();
			 try {
				 exit = p.process(command);
			 } catch(Exception e) {
				 e.printStackTrace(System.out);
			 }
		 }
		 System.out.println("Bye");
		 f.close();

	}



	private Account authenticate() {
		URL url = ProTrack.class.getClassLoader().getResource("authentication.config");
		String file = url.toExternalForm();
		System.setProperty("java.security.auth.login.config", file);
		try {
			loginContext = new LoginContext("ProTrackLogin", new TextCallbackHandler());
			loginContext.login();
			return Account.getAccount(loginContext.getSubject());
		} catch (LoginException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.exit(1);
			return null;
		}
		
	}
}
